package eu.dominicum.ft.pd;

import eu.dominicum.ft.pd.mao.MakeStageMAO;
import eu.dominicum.ft.pd.mao.MakeTeamMAO;
import eu.dominicum.ft.pd.mao.MakeTourMAO;

import java.util.ArrayList;
import java.util.List;

/**
 * A 'real' Tour de France.
 *
 * @author Harry Klerks
 * @since 2013M1
 */
public class Tour extends PersistentDomainObject {

    /**
     * The name of the Tour.
     */
    private String name;

    /**
     * This Tour's Stages.
     */
    private final List<Stage> stages = new ArrayList<>();

    /**
     * This Tour's teams.
     */
    private final List<Team> teams = new ArrayList<>();

    /**
     * A protected constructor to satisfy JPA.
     */
    protected Tour() {

    }

    /**
     * .
     *
     * @return String
     */
    public final String getName() {
        return name;
    }

    /**
     * Make a Tour.
     *
     * @param makeTourMAO - The Method Arguments Object
     * @return Tour
     */
    public static Tour make(final MakeTourMAO makeTourMAO) {

        Tour newTour = new Tour();

        newTour.name = makeTourMAO.getName();

        MakeStageMAO makeStageMAO;
        Stage newStage;
        if (makeTourMAO.getPrologue()) {
            makeStageMAO = new MakeStageMAO();
            makeStageMAO.setSequence(0);
            makeStageMAO.setTour(newTour);
            newStage = Stage.make(makeStageMAO);
            newTour.addToStages(newStage);
        }
        Integer stageSequence = 1;
        while (stageSequence <= makeTourMAO.getNumberOfStages()) {
            makeStageMAO = new MakeStageMAO();
            makeStageMAO.setSequence(stageSequence++);
            makeStageMAO.setTour(newTour);
            newStage = Stage.make(makeStageMAO);
            newTour.addToStages(newStage);
        }

        MakeTeamMAO makeTeamMAO;
        Team newTeam;
        Integer teamSequence = 1;
        while (teamSequence <= makeTourMAO.getNumberOfTeams()) {
            makeTeamMAO = new MakeTeamMAO();
            makeTeamMAO.setSequence(teamSequence++);
            makeTeamMAO.setYerseyNumberLow(makeTourMAO.getYerseyNumberLow());
            makeTeamMAO.setYerseyNumberHigh(makeTourMAO.getYerseyNumberHigh());
            makeTeamMAO.setTour(newTour);
            newTeam = Team.make(makeTeamMAO);
            newTour.addToTeams(newTeam);
        }

        return newTour;
    }

    /**
     * Adds the given {@link Stage} object to the list of associated
     * {@link Stage} objects.
     *
     * @param stage -
     */
    private void addToStages(final Stage stage) {

        this.stages.add(stage);
    }

    /**
     * Adds the given {@link Team} object to the list of associated
     * {@link Team} objects.
     *
     * @param team -
     */
    private void addToTeams(final Team team) {

        this.teams.add(team);
    }

    @Override
    public final String toString() {

        StringBuilder stringBuilder = new StringBuilder("Tour{");
        stringBuilder.append("name=");
        stringBuilder.append(this.name);
        stringBuilder.append("}");

        return stringBuilder.toString();
    }

    /**
     * .
     *
     * @return List<Stage>
     */
    public final List<Stage> getStages() {
        return stages;
    }

    /**
     * .
     *
     * @return List<Team>
     */
    public final List<Team> getTeams() {
        return teams;
    }

    /**
     * Find a Stage object identified by the given Id.
     *
     * @param stageId -
     * @return Stage
     */
    public final Stage findStageById(final Long stageId) {

        for (Stage stage : this.stages) {
            if (stage.getId() == stageId) {
                return stage;
            }
        }

        return null;
    }

    /**
     * Find a Team member by the given yersey number.
     *
     * @param yerseyNumber -
     * @return TeamMember
     */
    public final TeamMember findTeamMemberByYerseyNumber(final Integer yerseyNumber) {

        TeamMember teamMember = null;
        for (Team team : this.teams) {
            teamMember = team.findTeamMemberByYerseyNumber(yerseyNumber);
            if (teamMember != null) {
                return teamMember;
            }
        }

        return teamMember;
    }
}
